package com.spa.application.service.admin;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.spa.application.dto.PageResult;
import com.spa.application.dto.admin.OrderDetailDTO;
import com.spa.application.dto.admin.OrderExportDTO;
import com.spa.application.dto.admin.OrderListDTO;
import com.spa.application.dto.admin.TransferOrderExportDTO;
import com.spa.application.dto.admin.TransferOrderPageDTO;
import com.spa.application.query.admin.OrderDetailQuery;
import com.spa.application.query.admin.OrderExportQuery;
import com.spa.application.query.admin.OrderQuery;
import com.spa.application.query.admin.TransferOrderPageQuery;
import com.spa.domain.entity.*;
import com.spa.domain.service.*;
import com.spa.infrastructure.enums.dict.SourceEnum;
import com.spa.infrastructure.enums.dict.order.OrderStatusEnum;
import com.spa.infrastructure.mapper.OrderMapperStruct;
import com.spa.infrastructure.mapper.OrderTransferMapperStruct;
import com.spa.infrastructure.repository.condition.OrderInfoCondition;
import com.spa.infrastructure.repository.condition.OrderTransferCondition;
import com.spa.infrastructure.util.CurrencyUtils;
import com.spa.infrastructure.util.SessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AdminOrderService {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderTransferService orderTransferService;

    @Autowired
    private ProfitService profitService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private SysAdminUserService sysAdminUserService;

    public PageResult<OrderListDTO> listOrder(OrderQuery query) {

        OrderInfoCondition orderInfoCondition = OrderMapperStruct.INSTANCE.query2Condition4Page(query);
        List<Long> shopIds = sysAdminUserService.getMyDataPermission();
        orderInfoCondition.setShopIds(shopIds);
        OrderService.OrderInfoPlug plug = OrderService.OrderInfoPlug.base();
        Page<OrderInfo> orderInfoPage = orderService.pageByCondition(orderInfoCondition, plug);
        PageResult<OrderListDTO> orderListDTOPageResult = OrderMapperStruct.INSTANCE.entity2AdminOrderListDTO4Page(orderInfoPage);
        List<OrderListDTO> orderListDTOList = orderListDTOPageResult.getRecords();
        List<Long> orderIds = orderListDTOList.stream().map(OrderListDTO::getOrderId).toList();
        OrderTransferCondition condition = new OrderTransferCondition();
        condition.setOrderIds(orderIds);
        condition.setAscCreateTime("asc");//todo
        List<OrderTransfer> orderTransfers = orderTransferService.listByCondition(condition);
        Map<Long, OrderTransfer> map = orderTransfers.stream().collect(Collectors.toMap(OrderTransfer::getOrderId, Function.identity(), (k1, k2) -> k1));
        orderListDTOList.forEach(orderListDTO -> {
            OrderTransfer orderTransfer = map.getOrDefault(orderListDTO.getOrderId(), null);
            if (ObjectUtil.isNotEmpty(orderTransfer)) {
                orderListDTO.setTransferFlag(true);
                orderListDTO.setOldMassagistName(orderTransfer.getAppointMassagistName());
                orderListDTO.setOldMassagistPhone(orderTransfer.getAppointMassagistPhone());
            }else {
                orderListDTO.setTransferFlag(false);
                orderListDTO.setOldMassagistName(orderListDTO.getMassagistName());
                orderListDTO.setOldMassagistPhone(orderListDTO.getMassagistPhone());
            }
            List<Coupon> coupons = couponService.getCouponsByOrderId(orderListDTO.getOrderId());
            if (CollUtil.isNotEmpty(coupons)) {
                int couponPrice = coupons.get(0).getServicePrice() * coupons.size();
                orderListDTO.setSource(SourceEnum.byCode(coupons.get(0).getSource()).getDesc());
                orderListDTO.setActualPrice(orderListDTO.getActualPrice() - couponPrice);
            }
        });
        return orderListDTOPageResult;
    }

    public OrderDetailDTO detailById(OrderDetailQuery query) {
        OrderService.OrderInfoPlug plug = OrderService.OrderInfoPlug.base();
        OrderDetailDTO orderDetailDTO =
                OrderMapperStruct.INSTANCE.entity2OrderDetailDto(orderService.getOrderInfoById(query.getOrderId(), plug));

        OrderTransferCondition condition = new OrderTransferCondition();
        condition.setOrderIds(Lists.newArrayList(orderDetailDTO.getOrderId()));
        condition.setAscCreateTime("asc");//todo
        List<OrderTransfer> orderTransfers = orderTransferService.listByCondition(condition);
        if (CollectionUtil.isNotEmpty(orderTransfers)) {
            OrderTransfer orderTransfer = orderTransfers.get(0);
            orderDetailDTO.setTransferFlag(true);
            if (ObjectUtil.isNotNull(orderTransfer)) {
                orderDetailDTO.setOldMassagistName(orderTransfer.getAppointMassagistName());
                orderDetailDTO.setOldMassagistPhone(orderTransfer.getAppointMassagistPhone());
            }
        }
        //分润信息
        List<Profit> profitList = profitService.queryProfitByOrderId(orderDetailDTO.getOrderId());
        if (CollUtil.isNotEmpty(profitList)) {
            if (orderDetailDTO.getOrderStatus().getCode() == 99) {
                orderDetailDTO.setMassagistIncome(profitList.stream().map(Profit::getTravelPrice).reduce(Integer::sum).get());
            } else {
                orderDetailDTO.setMassagistIncome(profitList.stream().map(Profit::getMassagistIncome).reduce(Integer::sum).get());
            }
            orderDetailDTO.setShopIncome(profitList.stream().map(Profit::getShopIncome).reduce(Integer::sum).get());
            orderDetailDTO.setAdminIncome(profitList.stream().map(Profit::getAdminIncome).reduce(Integer::sum).get());
        }
        List<Coupon> coupons = couponService.getCouponsByOrderId(orderDetailDTO.getOrderId());
        if (CollUtil.isNotEmpty(coupons)) {
            int couponPrice = coupons.get(0).getServicePrice() * coupons.size();
            orderDetailDTO.setOrderTotalPrice(String.valueOf(Integer.parseInt(orderDetailDTO.getOrderTotalPrice()) - couponPrice));
        }
        return orderDetailDTO;
    }

    public PageResult<TransferOrderPageDTO> transferPage(TransferOrderPageQuery query) {
        OrderTransferCondition condition = OrderTransferMapperStruct.INSTANCE.query2Condition(query);
        condition.setAll(true);
        Page<OrderTransfer> orderTransferPage = orderTransferService.page4GroupByOrderLimitOne(condition);
        OrderTransferCondition orderTransferCondition = new OrderTransferCondition();
        orderTransferCondition.setOrderIds(orderTransferPage.getRecords().stream().map(OrderTransfer::getOrderId).toList());
        orderTransferCondition.setAscCreateTime("asc");
        List<OrderTransfer> orderTransfers = orderTransferService.listByCondition(orderTransferCondition);
        Map<Long, OrderTransfer> map = orderTransfers.stream().collect(Collectors.toMap(OrderTransfer::getOrderId, Function.identity(), (k1, k2) -> k1));
        orderTransferPage.getRecords().forEach(orderTransfer -> {
            OrderTransfer orderTransfer1 = map.getOrDefault(orderTransfer.getOrderId(), null);
            if (ObjectUtil.isNotNull(orderTransfer1)) {
                orderTransfer.setAppointMassagistId(orderTransfer1.getAppointMassagistId());
                orderTransfer.setAppointMassagistPhone(orderTransfer1.getAppointMassagistPhone());
                orderTransfer.setAppointMassagistName(orderTransfer1.getAppointMassagistName());
            }
        });
        return OrderTransferMapperStruct.INSTANCE.entity2TransferOrderPageDTO(orderTransferPage);
    }

    public List<TransferOrderPageDTO> getTransferOrderByOrderCode(String orderCode) {
        OrderTransferCondition condition = new OrderTransferCondition();
        condition.setOrderCode(orderCode);
        condition.setAll(true);
        return OrderTransferMapperStruct.INSTANCE.entity2TransferOrderList(orderTransferService.listByCondition(condition));
    }

    public List<OrderExportDTO> listExportOrder(OrderExportQuery query) {
        OrderQuery queryCondition = new OrderQuery();
        BeanUtil.copyProperties(query, queryCondition);
        OrderInfoCondition orderInfoCondition = OrderMapperStruct.INSTANCE.query2Condition4Page(queryCondition);
        OrderService.OrderInfoPlug plug = OrderService.OrderInfoPlug.base();
        plug.setTicket(true);
        plug.setProfit(true);
        plug.setRefumd(true);
        /* 交易单号 */
        plug.setTrade(true);
        Page<OrderInfo> orderInfoPage = orderService.pageByCondition(orderInfoCondition, plug);
        List<OrderInfo> orderInfoList = orderInfoPage.getRecords();
        List<OrderExportDTO> orderExportDTOList = new ArrayList<>();
        if (CollUtil.isNotEmpty(orderInfoList)) {
            buildOrderExportDTO(orderExportDTOList, orderInfoList);
        }
        return orderExportDTOList;
    }

    private void buildOrderExportDTO(List<OrderExportDTO> orderExportDTOList, List<OrderInfo> records) {
        AtomicInteger ai = new AtomicInteger(1);
        records.stream().forEach(a -> {
            OrderExportDTO orderExportDTO = new OrderExportDTO();
            orderExportDTO.setSeq(ai.getAndIncrement());
            orderExportDTO.setShopName(a.getShopName());
            orderExportDTO.setOrderCode(a.getOrderCode());
            orderExportDTO.setTransactionId(a.getTransactionId());
            orderExportDTO.setOrderStatusName(OrderStatusEnum.byCode(a.getStatus()).getDesc());

            MassageServiceEntity massageServiceEntity = a.getMassageService();
            if (BeanUtil.isNotEmpty(massageServiceEntity)) {
                orderExportDTO.setServiceName(massageServiceEntity.getName());
                orderExportDTO.setServiceMoney(CurrencyUtils.fenToYuan(massageServiceEntity.getDiscountPrice() * a.getOrderCount()).toString());
            }

            orderExportDTO.setMassagistName(a.getMassagistName());

            orderExportDTO.setOrderTime(a.getCreateTime());
            orderExportDTO.setExtTotalPrice(CurrencyUtils.fenToYuan(a.getExtTotalPrice()).toString());
            orderExportDTO.setTravelPrice(CurrencyUtils.fenToYuan(a.getTravelPrice()).toString());
            orderExportDTO.setOrderTotalMoney(CurrencyUtils.fenToYuan(a.getOrderTotalPrice()).toString());
            orderExportDTO.setPriceType(a.getPriceType());

            OrderAddress orderAddress = a.getOrderAddress();
            if (BeanUtil.isNotEmpty(orderAddress)) {
                orderExportDTO.setCustomerName(orderAddress.getName());
            }

            UserTicket userTicket = a.getTicket();
            if (BeanUtil.isNotEmpty(userTicket)) {
                orderExportDTO.setTicketMoney(CurrencyUtils.fenToYuan(userTicket.getRmb()).toString());

            }

            List<Profit> profitList = a.getProfitList();
            if (CollUtil.isNotEmpty(profitList)) {

                int massagistIncome = profitList.stream().map(Profit::getMassagistIncome).
                        filter(Objects::nonNull).reduce(Integer::sum).orElse(0);
                int travelPrice = profitList.stream().map(Profit::getTravelPrice).
                        filter(Objects::nonNull).reduce(Integer::sum).orElse(0);
                int shopIncome = profitList.stream().map(Profit::getShopIncome).
                        filter(Objects::nonNull).reduce(Integer::sum).orElse(0);
                int adminIncome = profitList.stream().map(Profit::getAdminIncome).
                        filter(Objects::nonNull).reduce(Integer::sum).orElse(0);

                orderExportDTO.setMassagistBrokerageMoney(CurrencyUtils.fenToYuan(massagistIncome).toString());
                orderExportDTO.setAmountPayableMassagistTrip(CurrencyUtils.fenToYuan(travelPrice).toString());
                orderExportDTO.setShopBrokerageMoney(CurrencyUtils.fenToYuan(shopIncome).toString());
                orderExportDTO.setPlatformBrokerageMoney(CurrencyUtils.fenToYuan(adminIncome).toString());
            }
            orderExportDTO.setRefundMoney(CurrencyUtils.fenToYuan(a.getRefundTotalMoney()).toString());
            orderExportDTOList.add(orderExportDTO);

        });

    }

    public List<TransferOrderExportDTO> listExportTransferOrder(TransferOrderPageQuery query) {
        OrderTransferCondition condition = OrderTransferMapperStruct.INSTANCE.query2Condition(query);
        condition.setDescCreateTime("desc");//todo
        return OrderTransferMapperStruct.INSTANCE.entity2TransferOrderExportDTO(orderTransferService.listByCondition(condition));
    }
}
